<?php

/*
=====================================================
 FluxBB - Delux Board Converstations (DBC)
-----------------------------------------------------
 http://dbc-forum.com/
 http://fluxbb.org/
-----------------------------------------------------
 Copyright (c) 2010,2011 FluxBB - Delux Board Conversations (DBC)
-----------------------------------------------------
 Предсловие: Данный скрипт (DBC) не является работой с нуля, то 
 есть ядром скрипта всё также остаётся FuxBB,но теперь в оболочке
 DBC.
=====================================================
*/

define('DBC_QUIET_VISIT', 1);

if (!defined('DBC_ROOT'))
	define('DBC_ROOT', './');
require DBC_ROOT.'engine/common.php';

// The length at which topic subjects will be truncated (for HTML output)
if (!defined('FORUM_EXTERN_MAX_SUBJECT_LENGTH'))
	define('FORUM_EXTERN_MAX_SUBJECT_LENGTH', 30);

// If we're a guest and we've sent a username/pass, we can try to authenticate using those details
if ($DBC_user['is_guest'] && isset($_SERVER['PHP_AUTH_USER']))
	authenticate_user($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);

if ($DBC_user['g_read_board'] == '0')
{
	http_authenticate_user();
	exit($lang_common['No view']);
}

$action = isset($_GET['action']) ? strtolower($_GET['action']) : 'feed';

// Handle a couple old formats, from Delux Board Conversations 1.2
switch ($action)
{
	case 'active':
		$action = 'feed';
		$_GET['order'] = 'last_post';
		break;

	case 'new':
		$action = 'feed';
		$_GET['order'] = 'posted';
		break;
}


//
// Sends the proper headers for Basic HTTP Authentication
//
function http_authenticate_user()
{
	global $DBC_config, $DBC_user;

	if (!$DBC_user['is_guest'])
		return;

	header('WWW-Authenticate: Basic realm="'.$DBC_config['o_board_title'].' External Syndication"');
	header('HTTP/1.0 401 Unauthorized');
}


//
// Output $feed as RSS 2.0
//
function output_rss($feed)
{
	global $lang_common, $DBC_config;

	// Send XML/no cache headers
	header('Content-Type: application/xml; charset=utf-8');
	header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Pragma: public');

	echo '<?xml version="1.0" encoding="utf-8"?>'."\n";
	echo '<rss version="2.0">'."\n";
	echo "\t".'<channel>'."\n";
	echo "\t\t".'<title><![CDATA['.escape_cdata($feed['title']).']]></title>'."\n";
	echo "\t\t".'<link>'.$feed['link'].'</link>'."\n";
	echo "\t\t".'<description><![CDATA['.escape_cdata($feed['description']).']]></description>'."\n";
	echo "\t\t".'<lastBuildDate>'.gmdate('r', count($feed['items']) ? $feed['items'][0]['pubdate'] : time()).'</lastBuildDate>'."\n";

	if ($DBC_config['o_show_version'] == '1')
		echo "\t\t".'<generator>Delux Board Conversations '.$DBC_config['o_cur_version'].'</generator>'."\n";
	else
		echo "\t\t".'<generator>Delux Board Conversations</generator>'."\n";

	foreach ($feed['items'] as $item)
	{
		echo "\t\t".'<item>'."\n";
		echo "\t\t\t".'<title><![CDATA['.escape_cdata($item['title']).']]></title>'."\n";
		echo "\t\t\t".'<link>'.$item['link'].'</link>'."\n";
		echo "\t\t\t".'<description><![CDATA['.escape_cdata($item['description']).']]></description>'."\n";
		echo "\t\t\t".'<author><![CDATA['.(isset($item['author']['email']) ? escape_cdata($item['author']['email']) : 'dummy@example.com').' ('.escape_cdata($item['author']['name']).')]]></author>'."\n";
		echo "\t\t\t".'<pubDate>'.gmdate('r', $item['pubdate']).'</pubDate>'."\n";
		echo "\t\t\t".'<guid>'.$item['link'].'</guid>'."\n";

		echo "\t\t".'</item>'."\n";
	}

	echo "\t".'</channel>'."\n";
	echo '</rss>'."\n";
}


//
// Output $feed as Atom 1.0
//
function output_atom($feed)
{
	global $lang_common, $DBC_config;

	// Send XML/no cache headers
	header('Content-Type: application/atom+xml; charset=utf-8');
	header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Pragma: public');

	echo '<?xml version="1.0" encoding="utf-8"?>'."\n";
	echo '<feed xmlns="http://www.w3.org/2005/Atom">'."\n";

	echo "\t".'<title type="html"><![CDATA['.escape_cdata($feed['title']).']]></title>'."\n";
	echo "\t".'<link rel="self" href="'.DBC_htmlspecialchars(get_current_url()).'"/>'."\n";
	echo "\t".'<link href="'.$feed['link'].'"/>'."\n";
	echo "\t".'<updated>'.gmdate('Y-m-d\TH:i:s\Z', count($feed['items']) ? $feed['items'][0]['pubdate'] : time()).'</updated>'."\n";

	if ($DBC_config['o_show_version'] == '1')
		echo "\t".'<generator version="'.$DBC_config['o_cur_version'].'">Delux Board Conversations</generator>'."\n";
	else
		echo "\t".'<generator>Delux Board Conversations</generator>'."\n";

	echo "\t".'<id>'.$feed['link'].'</id>'."\n";

	$content_tag = ($feed['type'] == 'posts') ? 'content' : 'summary';

	foreach ($feed['items'] as $item)
	{
		echo "\t".'<entry>'."\n";
		echo "\t\t".'<title type="html"><![CDATA['.escape_cdata($item['title']).']]></title>'."\n";
		echo "\t\t".'<link rel="alternate" href="'.$item['link'].'"/>'."\n";
		echo "\t\t".'<'.$content_tag.' type="html"><![CDATA['.escape_cdata($item['description']).']]></'.$content_tag.'>'."\n";
		echo "\t\t".'<author>'."\n";
		echo "\t\t\t".'<name><![CDATA['.escape_cdata($item['author']['name']).']]></name>'."\n";

		if (isset($item['author']['email']))
			echo "\t\t\t".'<email><![CDATA['.escape_cdata($item['author']['email']).']]></email>'."\n";

		if (isset($item['author']['uri']))
			echo "\t\t\t".'<uri>'.$item['author']['uri'].'</uri>'."\n";

		echo "\t\t".'</author>'."\n";
		echo "\t\t".'<updated>'.gmdate('Y-m-d\TH:i:s\Z', $item['pubdate']).'</updated>'."\n";

		echo "\t\t".'<id>'.$item['link'].'</id>'."\n";
		echo "\t".'</entry>'."\n";
	}

	echo '</feed>'."\n";
}


//
// Output $feed as XML
//
function output_xml($feed)
{
	global $lang_common, $DBC_config;

	// Send XML/no cache headers
	header('Content-Type: application/xml; charset=utf-8');
	header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Pragma: public');

	echo '<?xml version="1.0" encoding="utf-8"?>'."\n";
	echo '<source>'."\n";
	echo "\t".'<url>'.$feed['link'].'</url>'."\n";

	$forum_tag = ($feed['type'] == 'posts') ? 'post' : 'topic';

	foreach ($feed['items'] as $item)
	{
		echo "\t".'<'.$forum_tag.' id="'.$item['id'].'">'."\n";

		echo "\t\t".'<title><![CDATA['.escape_cdata($item['title']).']]></title>'."\n";
		echo "\t\t".'<link>'.$item['link'].'</link>'."\n";
		echo "\t\t".'<content><![CDATA['.escape_cdata($item['description']).']]></content>'."\n";
		echo "\t\t".'<author>'."\n";
		echo "\t\t\t".'<name><![CDATA['.escape_cdata($item['author']['name']).']]></name>'."\n";

		if (isset($item['author']['email']))
			echo "\t\t\t".'<email><![CDATA['.escape_cdata($item['author']['email']).']]></email>'."\n";

		if (isset($item['author']['uri']))
			echo "\t\t\t".'<uri>'.$item['author']['uri'].'</uri>'."\n";

		echo "\t\t".'</author>'."\n";
		echo "\t\t".'<posted>'.gmdate('r', $item['pubdate']).'</posted>'."\n";

		echo "\t".'</'.$forum_tag.'>'."\n";
	}

	echo '</source>'."\n";
}


//
// Output $feed as HTML (using <li> tags)
//
function output_html($feed)
{

	// Send the Content-type header in case the web server is setup to send something else
	header('Content-type: text/html; charset=utf-8');
	header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Pragma: public');

	foreach ($feed['items'] as $item)
	{
		if (utf8_strlen($item['title']) > FORUM_EXTERN_MAX_SUBJECT_LENGTH)
			$subject_truncated = DBC_htmlspecialchars(DBC_trim(utf8_substr($item['title'], 0, (FORUM_EXTERN_MAX_SUBJECT_LENGTH - 5)))).' вЂ¦';
		else
			$subject_truncated = DBC_htmlspecialchars($item['title']);

		echo '<li><a href="'.$item['link'].'" title="'.DBC_htmlspecialchars($item['title']).'">'.$subject_truncated.'</a></li>'."\n";
	}
}

// Show recent discussions
if ($action == 'feed')
{
	require DBC_ROOT.'engine/parser.php';

	// Determine what type of feed to output
	$type = isset($_GET['type']) ? strtolower($_GET['type']) : 'html';
	if (!in_array($type, array('html', 'rss', 'atom', 'xml')))
		$type = 'html';

	$show = isset($_GET['show']) ? intval($_GET['show']) : 15;
	if ($show < 1 || $show > 50)
		$show = 15;

	// Was a topic ID supplied?
	if (isset($_GET['tid']))
	{
		$tid = intval($_GET['tid']);

		// Fetch topic subject
		$result = $db->query('SELECT t.subject, t.first_post_id FROM '.$db->prefix.'topics AS t LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id='.$DBC_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.moved_to IS NULL AND t.id='.$tid) or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
		if (!$db->num_rows($result))
		{
			http_authenticate_user();
			exit($lang_common['Bad request']);
		}

		$cur_topic = $db->fetch_assoc($result);

		if ($DBC_config['o_censoring'] == '1')
			$cur_topic['subject'] = censor_words($cur_topic['subject']);

		// Setup the feed
		$feed = array(
			'title' 		=>	$DBC_config['o_board_title'].$lang_common['Title separator'].$cur_topic['subject'],
			'link'			=>	$DBC_config['o_base_url'].'/topic_'.$tid,
			'description'		=>	sprintf($lang_common['RSS description topic'], $cur_topic['subject']),
			'items'			=>	array(),
			'type'			=>	'posts'
		);

		// Fetch $show posts
		$result = $db->query('SELECT p.id, p.poster, p.message, p.hide_smilies, p.posted, p.poster_id, u.email_setting, u.email, p.poster_email FROM '.$db->prefix.'posts AS p INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id WHERE p.topic_id='.$tid.' ORDER BY p.posted DESC LIMIT '.$show) or error('Unable to fetch post info', __FILE__, __LINE__, $db->error());
		while ($cur_post = $db->fetch_assoc($result))
		{
			$cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);

			$item = array(
				'id'			=>	$cur_post['id'],
				'title'			=>	$cur_topic['first_post_id'] == $cur_post['id'] ? $cur_topic['subject'] : $lang_common['RSS reply'].$cur_topic['subject'],
				'link'			=>	$DBC_config['o_base_url'].'/topics_'.$cur_post['id'].'#p'.$cur_post['id'],
				'description'		=>	$cur_post['message'],
				'author'		=>	array(
					'name'	=> $cur_post['poster'],
				),
				'pubdate'		=>	$cur_post['posted']
			);

			if ($cur_post['poster_id'] > 1)
			{
				if ($cur_post['email_setting'] == '0' && !$DBC_user['is_guest'])
					$item['author']['email'] = $cur_post['email'];

				$item['author']['uri'] = $DBC_config['o_base_url'].'/profile.php?id='.$cur_post['poster_id'];
			}
			else if ($cur_post['poster_email'] != '' && !$DBC_user['is_guest'])
				$item['author']['email'] = $cur_post['poster_email'];

			$feed['items'][] = $item;
		}

		$output_func = 'output_'.$type;
		$output_func($feed);
	}
	else
	{
		$order_posted = isset($_GET['order']) && strtolower($_GET['order']) == 'posted';
		$forum_name = '';
		$forum_sql = '';

		// Were any forum IDs supplied?
		if (isset($_GET['fid']) && is_scalar($_GET['fid']) && $_GET['fid'] != '')
		{
			$fids = explode(',', DBC_trim($_GET['fid']));
			$fids = array_map('intval', $fids);

			if (!empty($fids))
				$forum_sql .= ' AND t.forum_id IN('.implode(',', $fids).')';

			if (count($fids) == 1)
			{
				// Fetch forum name
				$result = $db->query('SELECT f.forum_name FROM '.$db->prefix.'forums AS f LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$DBC_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND f.id='.$fids[0]) or error('Unable to fetch forum name', __FILE__, __LINE__, $db->error());
				if ($db->num_rows($result))
					$forum_name = $lang_common['Title separator'].$db->result($result);
			}
		}

		// Any forum IDs to exclude?
		if (isset($_GET['nfid']) && is_scalar($_GET['nfid']) && $_GET['nfid'] != '')
		{
			$nfids = explode(',', DBC_trim($_GET['nfid']));
			$nfids = array_map('intval', $nfids);

			if (!empty($nfids))
				$forum_sql .= ' AND t.forum_id NOT IN('.implode(',', $nfids).')';
		}

		// Setup the feed
		$feed = array(
			'title' 		=>	$DBC_config['o_board_title'].$forum_name,
			'link'			=>	$DBC_config['o_base_url'].'/index.php',
			'description'	=>	sprintf($lang_common['RSS description'], $DBC_config['o_board_title']),
			'items'			=>	array(),
			'type'			=>	'topics'
		);

		// Fetch $show topics
		$result = $db->query('SELECT t.id, t.poster, t.subject, t.posted, t.last_post, t.last_poster, p.message, p.hide_smilies, u.email_setting, u.email, p.poster_id, p.poster_email FROM '.$db->prefix.'topics AS t INNER JOIN '.$db->prefix.'posts AS p ON p.id='.($order_posted ? 't.first_post_id' : 't.last_post_id').' INNER JOIN '.$db->prefix.'users AS u ON u.id=p.poster_id LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=t.forum_id AND fp.group_id='.$DBC_user['g_id'].') WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.moved_to IS NULL'.$forum_sql.' ORDER BY '.($order_posted ? 't.posted' : 't.last_post').' DESC LIMIT '.$show) or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());
		while ($cur_topic = $db->fetch_assoc($result))
		{
			if ($DBC_config['o_censoring'] == '1')
				$cur_topic['subject'] = censor_words($cur_topic['subject']);

			$cur_topic['message'] = parse_message($cur_topic['message'], $cur_topic['hide_smilies']);

			$item = array(
				'id'			=>	$cur_topic['id'],
				'title'			=>	$cur_topic['subject'],
				'link'			=>	$DBC_config['o_base_url'].($order_posted ? '/topics_'.$cur_topic['id'] : '/topics_'.$cur_topic['id'].'&amp;action=new'),
				'description'	=>	$cur_topic['message'],
				'author'		=>	array(
					'name'	=> $order_posted ? $cur_topic['poster'] : $cur_topic['last_poster']
				),
				'pubdate'		=>	$order_posted ? $cur_topic['posted'] : $cur_topic['last_post']
			);

			if ($cur_topic['poster_id'] > 1)
			{
				if ($cur_topic['email_setting'] == '0' && !$DBC_user['is_guest'])
					$item['author']['email'] = $cur_topic['email'];

				$item['author']['uri'] = $DBC_config['o_base_url'].'/profile.php?id='.$cur_topic['poster_id'];
			}
			else if ($cur_topic['poster_email'] != '' && !$DBC_user['is_guest'])
				$item['author']['email'] = $cur_topic['poster_email'];

			$feed['items'][] = $item;
		}

		$output_func = 'output_'.$type;
		$output_func($feed);
	}

	exit;
}

// Show users online
else if ($action == 'online' || $action == 'online_full')
{
	// Load the index.php language file
	require DBC_ROOT.'language/'.$DBC_config['o_default_lang'].'/index.php';

	// Fetch users online info and generate strings for output
	$num_guests = $num_users = 0;
	$users = array();

	$result = $db->query('SELECT user_id, ident FROM '.$db->prefix.'online WHERE idle=0 ORDER BY ident', true) or error('Unable to fetch online list', __FILE__, __LINE__, $db->error());

	while ($DBC_user_online = $db->fetch_assoc($result))
	{
		if ($DBC_user_online['user_id'] > 1)
		{
			$users[] = ($DBC_user['g_view_users'] == '1') ? '<a href="'.$DBC_config['o_base_url'].'/profile.php?id='.$DBC_user_online['user_id'].'">'.DBC_htmlspecialchars($DBC_user_online['ident']).'</a>' : DBC_htmlspecialchars($DBC_user_online['ident']);
			++$num_users;
		}
		else
			++$num_guests;
	}

	// Send the Content-type header in case the web server is setup to send something else
	header('Content-type: text/html; charset=utf-8');
	header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Pragma: public');

	if ($action == 'online_full' && !empty($users))
		echo sprintf($lang_index['Users online'], implode(', ', $users)).'<br />'."\n";
	else
		echo sprintf($lang_index['Users online'], forum_number_format($num_users)).'<br />'."\n";

	echo sprintf($lang_index['Guests online'], forum_number_format($num_guests)).'<br />'."\n";

	exit;
}

// Show board statistics
else if ($action == 'stats')
{
	// Load the index.php language file
	require DBC_ROOT.'language/'.$DBC_config['o_default_lang'].'/index.php';

	// Collect some statistics from the database
	$result = $db->query('SELECT COUNT(id)-1 FROM '.$db->prefix.'users WHERE group_id!='.DBC_UNVERIFIED) or error('Unable to fetch total user count', __FILE__, __LINE__, $db->error());
	$stats['total_users'] = $db->result($result);

	$result = $db->query('SELECT id, username FROM '.$db->prefix.'users WHERE group_id!='.DBC_UNVERIFIED.' ORDER BY registered DESC LIMIT 1') or error('Unable to fetch newest registered user', __FILE__, __LINE__, $db->error());
	$stats['last_user'] = $db->fetch_assoc($result);

	$result = $db->query('SELECT SUM(num_topics), SUM(num_posts) FROM '.$db->prefix.'forums') or error('Unable to fetch topic/post count', __FILE__, __LINE__, $db->error());
	list($stats['total_topics'], $stats['total_posts']) = $db->fetch_row($result);

	// Send the Content-type header in case the web server is setup to send something else
	header('Content-type: text/html; charset=utf-8');
	header('Expires: '.gmdate('D, d M Y H:i:s').' GMT');
	header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
	header('Pragma: public');

	echo sprintf($lang_index['No of users'], forum_number_format($stats['total_users'])).'<br />'."\n";
	echo sprintf($lang_index['Newest user'], (($DBC_user['g_view_users'] == '1') ? '<a href="'.$DBC_config['o_base_url'].'/profile.php?id='.$stats['last_user']['id'].'">'.DBC_htmlspecialchars($stats['last_user']['username']).'</a>' : DBC_htmlspecialchars($stats['last_user']['username']))).'<br />'."\n";
	echo sprintf($lang_index['No of topics'], forum_number_format($stats['total_topics'])).'<br />'."\n";
	echo sprintf($lang_index['No of posts'], forum_number_format($stats['total_posts'])).'<br />'."\n";

	exit;
}

// If we end up here, the script was called with some wacky parameters
exit($lang_common['Bad request']);
